﻿// Copyright: http://stackoverflow.com/questions/16667072/wpf-how-to-draw-arc-with-radius-and-start-and-stop-angle

using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;

namespace Byond.PatchUiControls
{
	public sealed class Arc : Shape
	{
		#region Center DP

		public Point Center
		{
			get { return (Point)GetValue(CenterProperty); }
			set { SetValue(CenterProperty, value); }
		}

		// Using a DependencyProperty as the backing store for Center.  This enables animation, styling, binding, etc...
		public static readonly DependencyProperty CenterProperty =
			DependencyProperty.Register("Center", typeof(Point), typeof(Arc), new FrameworkPropertyMetadata(new Point(0, 0), FrameworkPropertyMetadataOptions.AffectsRender));

		#endregion

		#region StartAngle

		public double StartAngle
		{
			get { return (double)GetValue(StartAngleProperty); }
			set { SetValue(StartAngleProperty, value); }
		}

		// Using a DependencyProperty as the backing store for StartAngle.  This enables animation, styling, binding, etc...
		public static readonly DependencyProperty StartAngleProperty =
			DependencyProperty.Register("StartAngle", typeof(double), typeof(Arc), new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.AffectsRender));

		#endregion

		#region EndAngle

		public double EndAngle
		{
			get { return (double)GetValue(EndAngleProperty); }
			set { SetValue(EndAngleProperty, value); }
		}

		// Using a DependencyProperty as the backing store for EndAngle.  This enables animation, styling, binding, etc...
		public static readonly DependencyProperty EndAngleProperty =
			DependencyProperty.Register("EndAngle", typeof(double), typeof(Arc)
				, new FrameworkPropertyMetadata(Math.PI / 2.0, FrameworkPropertyMetadataOptions.AffectsRender));

		#endregion

		#region Radius

		public double Radius
		{
			get { return (double)GetValue(RadiusProperty); }
			set { SetValue(RadiusProperty, value); }
		}

		// Using a DependencyProperty as the backing store for Radius.  This enables animation, styling, binding, etc...
		public static readonly DependencyProperty RadiusProperty =
			DependencyProperty.Register("Radius", typeof(double), typeof(Arc), new FrameworkPropertyMetadata(10.0, FrameworkPropertyMetadataOptions.AffectsRender));

		#endregion

		#region SmallAngle

		public bool SmallAngle
		{
			get { return (bool)GetValue(SmallAngleProperty); }
			set { SetValue(SmallAngleProperty, value); }
		}

		// Using a DependencyProperty as the backing store for SmallAngle.  This enables animation, styling, binding, etc...
		public static readonly DependencyProperty SmallAngleProperty =
			DependencyProperty.Register("SmallAngle", typeof(bool), typeof(Arc), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsRender));

		#endregion

		static Arc()
		{
			DefaultStyleKeyProperty.OverrideMetadata(typeof(Arc),
				new FrameworkPropertyMetadata(typeof(Arc)));
		}

		protected override Geometry DefiningGeometry
		{
			get
			{
				var a0 = StartAngle < 0 ? StartAngle + 2 * Math.PI : StartAngle;
				var a1 = EndAngle < 0 ? EndAngle + 2 * Math.PI : EndAngle;

				if (a1 < a0)
					a1 += Math.PI * 2;

				var d = SweepDirection.Counterclockwise;
				bool large;

				if (SmallAngle)
				{
					large = false;
					d = (a1 - a0) > Math.PI
						? SweepDirection.Counterclockwise
						: SweepDirection.Clockwise;
				}
				else
					large = (Math.Abs(a1 - a0) < Math.PI);

				var p0 = Center + new Vector(Math.Cos(a0), Math.Sin(a0)) * Radius;
				var p1 = Center + new Vector(Math.Cos(a1), Math.Sin(a1)) * Radius;

				var segments = new List<PathSegment>(1)
					{
						new ArcSegment(p1, new Size(Radius, Radius), 0.0, large, d, true)
					};

				var figures = new List<PathFigure>(1);
				var pf = new PathFigure(p0, segments, true)
					{
						IsClosed = false
					};
				figures.Add(pf);

				return new PathGeometry(figures, FillRule.EvenOdd, null);
			}
		}
	}
}